import abc


class Sample:
    def __init__(self, sample_id: int, seed: int = 42):
        self.__id = sample_id
        self.__seed = seed

    @property
    def sample_id(self) -> int:
        return self.__id

    @property
    def seed(self) -> int:
        return self.__seed

    @seed.setter
    def seed(self, value: int):
        assert isinstance(value, int)
        self.__seed = value


class ChoiceSample(Sample):
    def __init__(self, sample_id: int, candidates: list, seed: int = 42):
        Sample.__init__(self, sample_id, seed=seed)
        self.__candidates = candidates

    @property
    def candidates(self) -> list:
        return self.__candidates


class PromptSample(Sample):
    def __init__(self, sample_id: int, prompt: str, seed: int = 42):
        Sample.__init__(self, sample_id, seed=seed)
        self.__prompt = prompt

    @property
    def prompt(self) -> str:
        return self.__prompt


class PromptClassificationSample(PromptSample, metaclass=abc.ABCMeta):
    def __init__(self, sample_id: int, prompt: str, seed: int = 42):
        super().__init__(sample_id, prompt, seed=seed)

    @abc.abstractmethod
    def fill_prompt_with_label_content(self, label_content: str) -> str:
        pass


class PromptChoiceSample(ChoiceSample, PromptSample, metaclass=abc.ABCMeta):
    def __init__(self, sample_id: int, candidates: list,
                 prompt: str, seed: int = 42):
        ChoiceSample.__init__(self, sample_id, candidates, seed=seed)
        PromptSample.__init__(self, sample_id, prompt, seed=seed)

    @abc.abstractmethod
    def fill_prompt_with_candidate(self, candidate) -> str:
        pass
